<?php
namespace WDB\Wrapper;
use WDB;

/**
 * @author Richard Ejem <richard(at)ejem.cz>
 * @package WDB
 */
final class Field extends WDB\BaseObject
{
    /**@var iColumn $columnWrapper*/
    private $column;
    /**@var mixed */
    private $originalValue;
    /**@var mixed */
    private $newValue;
    private $written = FALSE;
    private $validationErrors = array();

    /**
     *
     * @param iColumn column this field belongs to
     * @param bool is in new record
     * @param mixed field value
     */
    public function __construct(iColumn $column, $isNew, $value)
    {
        $this->column = $column;
        if ($isNew)
        {
            $this->originalValue = $column->getDefault();
            $this->newValue = $value;
            $this->written = TRUE;
        }
        else
        {
            $this->originalValue = $value;
            $this->newValue = FALSE;
        }
    }

    /**
     * Adds a validation error on this field.
     *
     * @param string error message
     */
    public function addValidationError($message)
    {
        $this->validationErrors[] = $message;
    }

    /**
     * Erases all bound validation errors.
     */
    public function resetValidationErrors()
    {
        $this->validationErrors = array();
    }

    public function getValidationErrors()
    {
        return $this->validationErrors;
    }

    /**
     * Called when owner record is saved - updates original value to current value (Resets the changed state)
     *
     */
    public function saved()
    {
        if ($this->written)
        {
            $this->originalValue = $this->newValue;
        }
        $this->written = FALSE;
    }

    /**
     * Sets the value of the field.
     *
     * @param mixed the value
     * @return self fluent interface
     */
    public function setValue($value)
    {
        $this->newValue = $value;
        $this->written = TRUE;
        return $this;
    }

    /**
     * Gets the value of the field.
     *
     * @return mixed
     */
    public function getValue()
    {
        return $this->written ? $this->newValue : $this->originalValue;
    }

    public function getStringValue()
    {
        return $this->column->getStringValue($this->getValue());
    }

    /**
     * Returns true if the value has been changed since load (differs from the original value)
     *
     * @return bool
     */
    public function isChanged()
    {
        if (!$this->written) return false;
        if (is_object($this->newValue) && method_exists($this->newValue, 'equals'))
        {
            return $this->newValue->equals($this->originalValue);
        } else
        {
            return $this->newValue != $this->originalValue;
        }
    }

    /**
     * Returns true if the value has been written since load (may be equal to original value)
     *
     * @return bool
     */
    public function isWritten()
    {
        return $this->written;
    }

    /**
     * Returns the original value of this column as it was on load
     *
     * @return mixed
     */
    public function getOriginalValue()
    {
        return $this->originalValue;
    }

    /**
     * Adds a value to the array which represents the row which will be saved to database.
     *
     * @param array the row
     */
    public function saveToRow(array &$row)
    {
        $this->column->saveToRow($row, $this->value);
    }

    /**
     *
     * @return iColumn
     */
    public function getColumn()
    {
        return $this->column;
    }
}